package org.john.auth.server.service;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.john.auth.client.common.AuthClientConst;
import org.john.auth.client.common.AuthModelConst;
import org.john.auth.client.context.UserContext;
import org.john.auth.client.context.UserRedisContext;
import org.john.auth.client.model.User;
import org.john.auth.client.util.JwtTokenUtil;
import org.john.auth.client.vo.crequest.LoginParam;
import org.john.common.exception.AssertionException;
import org.john.common.util.Assertion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class AuthService {
	@Autowired
	private RedisTemplate redisTemplate;

	@Value("${jwt.expire:1800}")
	private long expire;

	public String login(LoginParam param) {
		// 1、校验逻辑

		String username = param.getUsername();
		String password = param.getPassword();

		Assertion.notEmpty(username, "用户名不能为空", HttpStatus.UNAUTHORIZED.value());
		Assertion.notEmpty(password, "密码不能为空", HttpStatus.UNAUTHORIZED.value());

		String digestPassword = DigestUtils.md5DigestAsHex(password.getBytes());

		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq(AuthModelConst.COLUMN_USER_USERNAME, username);
		User user = userService.getOne(queryWrapper);

		if (user == null || !digestPassword.equals(user.getPassword())) {
			throw new AssertionException(user != null ? "用户名或密码错误。" : "用户不存在");
		}

		// 3、生成token
		String token = generateToken(user);
		// TODO 记录日志
		return token;
	}

	public void logout(String token) {
		UserContext userContext = JwtTokenUtil.paseUserContext(token);
		long existExpire = redisTemplate.opsForValue().getOperations().getExpire(AuthClientConst.KEY_REDIS_TOKEN_PREFIX + userContext.getUniqueId());
		UserRedisContext userRedisContext = new UserRedisContext();
		userRedisContext.setEffective(false);
		redisTemplate.opsForValue().setIfPresent(AuthClientConst.KEY_REDIS_TOKEN_PREFIX + userContext.getUniqueId(), userRedisContext, existExpire, TimeUnit.SECONDS);
	}

	private String generateToken(User user) {
		// 1、根据user构造userContext
		long now = new Date().getTime();
		String uuid = UUID.randomUUID().toString().replaceAll("-", "");
		String uniqueId = user.getId() + "_" + uuid;
		UserContext userContext = new UserContext();
		userContext.setUniqueId(uniqueId);
		userContext.setUserId(user.getId());
		userContext.setRole(user.getRole());
		userContext.setIssuedAt(now);
		userContext.setExpireTime(now + 1000 * expire);

		// 2、通过userContext构造token
		String token = JwtTokenUtil.buildToken(userContext);

		// 3、token丢到中央缓存
		UserRedisContext userRedisContext = new UserRedisContext();
		redisTemplate.opsForValue().set(AuthClientConst.KEY_REDIS_TOKEN_PREFIX + uniqueId, userRedisContext, expire, TimeUnit.SECONDS);
		return token;
	}
}
